package com.leen.security.filter;

import com.leen.security.TokenService;
import com.leen.security.domain.AdminLoginUserDetails;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 *  判断每次是否登录，token是否有效 CheckLoginInterceptor.java
 *  OncePerRequestFilter顾名思义，他能够确保在一次请求只通过一次filter，而不需要重复执行
 *
 * @author admin
 * @date 2021-05-13
 */
@Log4j2
@Component
public class JwtAuthenticationTokenFilter  extends OncePerRequestFilter {

    @Autowired
    private TokenService tokenService;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
       //每一次spring security认证之前，先判断是否登录过，如果登录过就要把用户还原成 已认证的用户
        //根据令牌还原已登录用户信息
        String url=httpServletRequest.getRequestURI();

        AdminLoginUserDetails adminLoginUser=tokenService.getAdminLoginUser(httpServletRequest);
        //spring security取得当前用户信息
        Authentication  authentication= SecurityContextHolder.getContext().getAuthentication();
        log.debug("访问url={},是否登录={}",url,adminLoginUser!=null);
        //必须是redis中存在的， 而且 spring  security认为你已经登录了
        if(adminLoginUser!=null &&  authentication==null ){
           // 判断你登录时间是否快过期了，如果小于10分钟，重新续半小时
            tokenService.verifyToken(adminLoginUser);
            //把这个对象交给 spring security 认证
            UsernamePasswordAuthenticationToken  authenticationToken=new UsernamePasswordAuthenticationToken(adminLoginUser, null, adminLoginUser.getAuthorities());
            //增加额外数据
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));

            //交给spring security本地线程池来管理
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }

        //执行后续 spring security操作
        filterChain.doFilter(httpServletRequest,httpServletResponse);

    }
}
